﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using BDDfyIt.CodeDom;
using TestStack.BDDfy.Scanners.StepScanners.ExecutableAttribute.GwtAttributes;

namespace BDDfyIt.Core
{
    internal static class TextStoryExtensions
    {
        internal static TextStory StoryModel { get; set; }

        private static string _existingAttribute;
        private const string AsA = "AsA";
        private const string IWantTo = "IWant";
        private const string SoThat = "SoThat";
        private const string Given = "Given";
        private const string When = "When";
        private const string Then = "Then";
        private const string AndGiven = "AndGiven";
        private const string AndWhen = "AndWhen";
        private const string AndThen = "AndThen";

        internal static string GetMethodName(string type, string value)
        {
            var methodPrefix = GetMethodPrefix(type);
            var methodName = new StringBuilder();
            methodName.Append(methodPrefix);
            if (value.StartsWith("And"))
            {
                value = value.Replace("And", string.Empty);
            }
            methodName.Append(
                FormatNames(value));
            return methodName.ToString();
        }

        internal static string GetMethodPrefix(string firstWord)
        {
            if (string.Equals(firstWord, Given) || string.Equals(firstWord, When) || string.Equals(firstWord, Then))
            {
                _existingAttribute = firstWord;
                return firstWord;
            }
            if (string.Equals(_existingAttribute, Then))
            {
                return "And";
            }
            return string.Format("And{0}", _existingAttribute);
        }

        internal static string GetNamespace(string outputNamespace)
        {
            if (string.IsNullOrEmpty(outputNamespace))
            {
                outputNamespace = "BDDfyIt";
            }
            return outputNamespace;
        }

        internal static string GetClassName(string scenarioName, string outputClassName)
        {
            if (string.IsNullOrEmpty(outputClassName) == false)
            {
                return outputClassName;
            }
            outputClassName = "BDDfyItFixture";
            if (string.IsNullOrEmpty(StoryModel.Story.Name) == false)
            {
                outputClassName = FormatNames(StoryModel.Story.Name);
            }
            if (string.IsNullOrEmpty(scenarioName) == false)
            {
                outputClassName = FormatNames(scenarioName);
            }
            return outputClassName;
        }

        internal static void SetStoryAttributeValue(out List<string> storyAttributeArguments, out List<string> storyAttributeArgumentValues)
        {
            storyAttributeArguments = new List<string>();
            storyAttributeArgumentValues = new List<string>();
            if (string.IsNullOrEmpty(StoryModel.Story.AsA) == false)
            {
                storyAttributeArguments.Add(AsA);
                storyAttributeArgumentValues.Add(StoryModel.Story.AsA);
            }
            if (string.IsNullOrEmpty(StoryModel.Story.IWantTo) == false)
            {
                storyAttributeArguments.Add(IWantTo);
                storyAttributeArgumentValues.Add(StoryModel.Story.IWantTo);
            }
            if (string.IsNullOrEmpty(StoryModel.Story.SoThat) == false)
            {
                storyAttributeArguments.Add(SoThat);
                storyAttributeArgumentValues.Add(StoryModel.Story.SoThat);
            }
        }

        internal static Type GetAttributeType(string attribute)
        {
            if (string.Equals(attribute, Given))
            {
                return typeof(GivenAttribute);
            }
            if (string.Equals(attribute, AndGiven) || string.Equals(_existingAttribute, Given))
            {
                return typeof(AndGivenAttribute);
            }
            if (string.Equals(attribute, When))
            {
                return typeof(WhenAttribute);
            }
            if (string.Equals(attribute, AndWhen) || string.Equals(_existingAttribute, When))
            {
                return typeof(AndWhenAttribute);
            }
            if (string.Equals(attribute, Then))
            {
                return typeof(ThenAttribute);
            }
            if (string.Equals(attribute, AndThen) || string.Equals(_existingAttribute, Then))
            {
                return typeof(AndThenAttribute);
            }
            return null;
        }

        internal static void AddMethodToClass(CodeDomWrapper codeDomWrapper, string type, string value)
        {
            var methodName = GetMethodName(type, value);
            codeDomWrapper.CreateVoidMethod(methodName, "public");
            codeDomWrapper.CreateCustomAttributeOnMethod(GetAttributeType(type), new List<string> { "StepTitle" }, new List<string> { value });
            codeDomWrapper.AddMethodToClass();
        }

        private static string FormatNames(string name)
        {
            var formattedName = System.Threading.Thread.CurrentThread.CurrentCulture.TextInfo.ToTitleCase(name.ToLower());
            return formattedName.Replace(" ", string.Empty);
        }
    }
}
